import React from 'react';
import './reset.less';
import './global.css';
import styles from './index.less';
import FlowGraph from './Graph'
import ToolBar from './components/ToolBar/index';
import LeftDivs from './components/LeftDivs/index';


import insertCss from "insert-css";
import { Dom } from '@antv/x6'

import { saveDialogTemplate, copyDialogNode } from '@/services/dialog';
import { connect } from 'dva';
import { Form, message,Icon } from 'antd';
import UserSession from '@/UserSession';
import editIcon from '@/assets/dialog/edit.png'
import copyIcon from '@/assets/dialog/copy.png'
let graph;
let dnd;

const portCircles = {
  r: 5,
  magnet: true,
  stroke: '#5F95FF',
  strokeWidth: 1,
  fill: '#fff',
  style: {
    visibility: 'hidden',
  },
}
const ports = {
  groups: {
    top: {
      position: 'top',
      attrs: {
        circle: portCircles
      },
    },
    right: {
      position: 'right',
      attrs: {
        circle: portCircles
      },
    },
    bottom: {
      position: 'bottom',
      attrs: {
        circle: portCircles
      },
    },
    left: {
      position: 'left',
      attrs: {
        circle: portCircles
      },
    },
  },
  items: [{
    group: 'top',
    id: '0',
  }, {
    group: 'right',
    id: '3',
  }, {
    group: 'bottom',
    id: '1',
  }, {
    group: 'left',
    id: '2',
  }],
}
const startPorts = {
  groups: {
    outBottom: {
      position: { name: 'bottom' },
      attrs: {
        circle: portCircles
      },
    },
    outLeft: {
      position: { name: 'left' },
      attrs: {
        circle: portCircles
      },
    },
    outRight: {
      position: { name: 'right' },
      attrs: {
        circle: portCircles
      },
    }
  },
  items: [
    {
      group: 'outBottom',
      id: '0',
    },
    {
      group: 'outLeft',
      id: '1',
    },
    {
      group: 'outRight',
      id: '2',
    },
  ],
}
const endPorts = {
  groups: {
    inTop: {
      position: { name: 'top' },
      attrs: {
        circle: portCircles
      },
    },
    inLeft: {
      position: { name: 'left' },
      attrs: {
        circle: portCircles
      },
    },
    inRight: {
      position: { name: 'right' },
      attrs: {
        circle: portCircles
      },
    }
  },
  items: [
    {
      group: 'inTop',
      id: '0',
    },
    {
      group: 'inLeft',
      id: '1',
    },
    {
      group: 'inRight',
      id: '2',
    },
  ],
}

class FormFlow extends React.Component {
  constructor(props) {
    super(props);
    this.state = {}
    this.cell = null;
  }

  componentDidMount() {
    if (this.props.onRef) {
      this.props.onRef(this);
    };
    const _this = this;
    graph = FlowGraph.init();
    dnd = FlowGraph.initDnd();
    window.addEventListener('resize', this.resizeFn);
    const dom = document.getElementById('flowContent')
    const observer = new ResizeObserver(entries => {
      this.resizeFn()
    })
    
    observer.observe(dom);

    /**
		 * 初始化右键菜单--开始
		 */
		insertCss(`
      #contextDialogMenu {
        position: absolute;
        list-style-type: none;
        padding: 0;
        left: -150px;
        background-color: rgba(255, 255, 255,1);
        border-radius: 6px;
        font-size: 12px;
        color: #000000;
        position: absolute;
        z-index: 1011;
        display: none;
        box-shadow: 0px 1px 8px 0px rgba(201,201,201,0.59);
      }
      #contextDialogMenu .addPopoverNode {
        left: 50%;
        -webkit-transform: translateX(-50%) rotate(45deg);
        -ms-transform: translateX(-50%) rotate(45deg);
        transform: translateX(-50%) rotate(45deg);

        top: -4px;
        border-top-color: #fff;
        border-right-color: transparent;
        border-bottom-color: transparent;
        border-left-color: #fff;
        -webkit-box-shadow: -2px -2px 5px rgb(0 0 0 / 6%);
        box-shadow: -2px -2px 5px rgb(0 0 0 / 6%);

        position: absolute;
        display: block;
        width: 8px;
        height: 8px;
        background: 0 0;
        border-style: solid;
        border-width: 4px;
        -webkit-transform: rotate(45deg);
        -ms-transform: rotate(45deg);
        transform: rotate(45deg);
      }
      #contextDialogMenu li {
        cursor: pointer;
        list-style-type:none;
        list-style: none;
        margin-left: 0px;
        padding:10px;
        border:none;
        min-width:87px;
      }
      #contextDialogMenu li:hover {
        color: #000;
        background: #d5f3fe;
      }
      #contextDialogMenu li .icon {
        width: 16px;
        height: 16px;
        margin-right: 10px;
      }
      .reName {
        display:none;
      }
      .menuIcon{
        vertical-align:middle;
        margin-right:10px;
      }
      .menuText{
        vertical-align:middle;
      }
    `);
    const conextMenuContainer = document.createElement("ul");
    conextMenuContainer.id = "contextDialogMenu";

    // const addPopoverNodeLi = document.createElement("div");
    // addPopoverNodeLi.setAttribute("class", "addPopoverNode");
    // conextMenuContainer.appendChild(addPopoverNodeLi);

    const addClassNodeLi = document.createElement("li");
    addClassNodeLi.setAttribute("class", "addClassNode");

    const editLi = document.createElement("li");
    const editText = document.createElement("span");
    editText.innerHTML = !UserSession.isSystemKnowledge() ? `<img src="${editIcon}" class="menuIcon" /><span class="menuText">编辑</span>` : `<img src="${editIcon}" class="menuIcon" /><span class="menuText">查看</span>`;
    editLi.appendChild(editText);
    editLi.setAttribute("class", "editNode");
    conextMenuContainer.appendChild(editLi);

    const copyLi = document.createElement("li");
    const copyText = document.createElement("span");
    copyText.innerHTML = `<img src="${copyIcon}" class="menuIcon" style="width: 14px;" /><span class="menuText">复制</span>`;
    copyLi.appendChild(copyText);
    copyLi.setAttribute("class", "copyNode");
    conextMenuContainer.appendChild(copyLi);

    document.getElementById("container").appendChild(conextMenuContainer);

    graph.on('node:contextmenu', ({ cell, e }) => {
      // console.log(cell, cell.id, cell.label);
      _this.cell = { ...cell, id: cell.id, label: cell.label };
      switch (cell.label) {
        case 'start':
          conextMenuContainer.style.display = "none";
          this.openEdit(cell);
          break;

        case 'end':
          conextMenuContainer.style.display = "none";
          this.openEdit(cell);
          break;

        default:
          // conextMenuContainer.style.display = "block";
          // copyLi.style.display = UserSession.isSystemKnowledge() ? 'none' : "block";
          conextMenuContainer.style.display = "none";
          this.openEdit(cell);
          break;
      };
      const p = graph.clientToGraph(e.clientX, e.clientY);
      conextMenuContainer.style.left = `${p.x}px`;
			conextMenuContainer.style.top = `${p.y}px`;
    });

    if (!UserSession.isSystemKnowledge()) {
      graph.on('node:mouseenter', ({ node }) => {
        node.setAttrs({
          // 表示一个删除按钮，点击时删除该节点
          image: {
            xlinkHref: '/dialogImage/delete.png',
            event: 'node:delete',
            cursor: 'pointer',
          }
        })
      });
      graph.on('node:mouseleave', ({ node }) => {
        node.removeTools();
        node.removeAttrByPath('image');
      });
      const container = document.getElementById('container');
    };

    /**
     * 点击画布
     */
    graph.on("blank:click", (e) => {
			conextMenuContainer.style.left = "-150px";
			conextMenuContainer.style.display = "none";
      _this.cell = null;
		});

    /**
		 * 编辑节点
		 */
		editLi.addEventListener("click", function () {
			_this.openEditDrawer("#fff", "#000");
			conextMenuContainer.style.left = "-150px";
      conextMenuContainer.style.display = "none";
		});

    /**
		 * 复制节点
		 */
		copyLi.addEventListener("click", async () => {
      // console.log(_this.cell);
			let res = await copyDialogNode({ nodeType:_this.cell.label, oldNodeId: _this.cell.id.split('-')[0] });
      console.log(res);
      if (res.code === 0) {
        this.props.getDialogData();
        message.success('复制成功');
        conextMenuContainer.style.display = "none";
      };
		});

    this.judgeDataSource();
  }

  componentWillUnmount() {
    console.log('销毁了');
    //去掉浏览器监控大小，画布的自适应
    window.removeEventListener('resize', this.resizeFn);
  }

  /**
	 * 打开编辑节点弹窗
	 */
	openEditDrawer = () => {
    if (this.cell.label != 'end') {
      this.openEdit(this.cell)
    }
	};

  /**
   * 判断如何取值
   */
  judgeDataSource = () => {
    const { flowData } = this.props;
    if (flowData) {
      this.processTheData(flowData);
    } else {
      this.initFlowGraphData([]);
    }
  }

  /**
   * 处理接口取到的数据
   */
  processTheData = data => {
    console.log(data);
    const existNode = data.nodes.map(item => item.id);
    const cells = [];
    for (const node of data.nodes) {
      let nodeObj = {
        label: node.modal,
        shape: node.shape ? node.shape : 'rect',
        position: { x: node.x, y: node.y },
        width: 120,
        height: 70,
        id: node.id,
        ports
      };
      let config = { attrBaseConfig: {}, makeupBaseConfig: [] }
      switch (node.modal) {
        case 'start':
          config = this.setNodeConfig(node.label, '#DAE6FF', '#E2EBFF', 'rect', 8, 8,'start.png');
          nodeObj.ports = startPorts;
          break;
        case 'end':
          config = this.setNodeConfig(node.label, '#FFE8C5', '#FFEDD3', 'rect', 8, 8,'end.png');
          nodeObj.ports = endPorts;
          break;
        case 'field':
          config = this.setNodeConfig(node.label, '#F1DAFF', '#F3E1FF', 'rect', 8, 8,'field.png');
          break;
        case 'api':
          config = this.setNodeConfig(node.label, '#C3F4FF', '#D3F7FF', 'rect', 8, 8,'api.png');
          break;
        case 'store':
          config = this.setNodeConfig(node.label, '#C6E6BB', '#CFECC5', 'rect', 8, 8,'store.png');
          break;
        case 'confirm':
          config = this.setNodeConfig(node.label, '#FFD7D3', '#FFE6E3', 'rect', 8, 8,'confirm.png');
          break;
        case 'judge':
          config = this.setNodeConfig(node.label, '#FFDEDE', '#FFE0E0', 'polygon', 8, 8,'judge.png');
          nodeObj.shape = 'polygon'
          break;
      };
      nodeObj.attrs = config.attrBaseConfig;
      nodeObj.markup = config.makeupBaseConfig;
      cells.push(nodeObj);
    };
    for (const edge of data.edges) {
      if (existNode.indexOf(edge.source) !== -1 && existNode.indexOf(edge.target) != -1) {
        let edgeObj = {
          id: edge.id,
          shape: 'edge',
          source: {
            cell: edge.source,
            port: edge.sourceAnchor + ''
          },
          target: {
            cell: edge.target,
            port: edge.targetAnchor + '',
          },
          zIndex: 0,
          router: {
            name: "manhattan",
            args: {
              padding: 1
            }
          },
          attrs: {
            line: {
              stroke: "#0A172A",
              strokeWidth: 1,
              targetMarker: {
                name: "classic",
                size: 8
              }
            }
          },
          labels: edge.annotation ? [edge.annotation] : []
        };
        cells.push(edgeObj);
      }
    };

    this.initFlowGraphData({ cells })
  }

  /**
   * 渲染画图数据
   */
  initFlowGraphData = data => {
    setTimeout(() => {
      graph.fromJSON(data)
      this.resizeFn();
      if (data.cells && data.cells.length > 0) {
        graph.centerContent();
      } else {
        graph.center();
      }
    }, 300)
  }

  /**
   * 单击打开编辑页
   * @param flag
   */
  openEdit = (cell) => {
    let text = '';
    switch (cell.label) {
      case 'start':
        text = '开始模块';
        break;
      case 'field':
        text = '字段收集模块';
        break;
      case 'api':
        text = 'APIs模块';
        break;
      case 'judge':
        text = '判断模块';
        break;
      case 'store':
        text = '落表模块';
        break;
      case 'store':
        text = '信息确认模块';
        break;
      case 'end':
        text = '结束模块';
        break;
    };
    const selectNode = {
      title: text,
      model: cell.label,
      nodeType: '',
      id: cell.id.split('-')[0],
      cell
    };
    this.props.opRightDrawer(selectNode)
  }

  /**
   * 自适应屏幕
   * @param flag
   */
  resizeFn = () => {
    let width = document.getElementById('flowContent') ? document.getElementById('flowContent').offsetWidth - 170 : null;
    let height = document.getElementById('flowContent') ? document.getElementById('flowContent').offsetHeight - 40 : null;
    graph.resizeGraph(width, height)
    graph.resize(width, height);
    this.setState({ width })
  }

  /**
   * 拖拽事件
   * @param e
   * @param title
   * @param borderColor
   * @param backgroundColor
   * @param modal
   */
  startDrag = (e, title, borderColor, backgroundColor, modal) => {
    if (UserSession.whetherCanDelete()) {
      return false
    };

    const target = e.currentTarget
    const type = target.getAttribute('data-type')
    let node = ''
    switch(type){
      case 'start':
        node = this.creatStartNode(title)
        break;
      case 'end':
        node = this.creatEndNode(title)
        break;
      case 'rect':
        node = this.creatCenterNode(title,borderColor,backgroundColor,modal);
        break;
      case 'polygon':
        node = this.creatCaseNode(title)
        break;
    }

    dnd.start(node, e.nativeEvent)
  }

  /**
   * 创建开始节点
   */
  creatStartNode = (title) => {
    const config = this.setNodeConfig(title, '#DAE6FF', '#E2EBFF', 'rect', 8, 8,'start.png');
    console.log(config);
    return graph.createNode({
      label: 'start',
      shape: 'rect',
      width: 120,
      height: 70,
      attrs: config.attrBaseConfig,
      markup: config.makeupBaseConfig,
      ports: startPorts,
    })
  }

  /**
   * 创建rect节点
   */
  creatCenterNode = (title, borderColor, backgroundColor, modal) => {
    const config = this.setNodeConfig(title, borderColor, backgroundColor, 'rect', 8, 8,modal+'.png',40);
    console.log(config);
    return graph.createNode({
      label: modal,
      shape: 'rect',
      width: 120,
      height: 70,
      attrs: config.attrBaseConfig,
      markup: config.makeupBaseConfig,
      ports: ports,
    })
  }

  /**
   * 创建判断节点
   */
  creatCaseNode = (title) => {
    const config = this.setNodeConfig(title, '#FFDEDE', '#FFE0E0', 'polygon', 8, 8,'judge.png',42);
    console.log(config);
    return graph.createNode({
      label: 'judge',
      width: 120,
      height: 70,
      shape: 'polygon',
      attrs: config.attrBaseConfig,
      markup: config.makeupBaseConfig,
      ports: ports,
    })
  }

  /**
   * 创建结束节点
   */
  creatEndNode = (title) => {
    const config = this.setNodeConfig(title, '#FFE8C5', '#FFEDD3', 'rect', 8, 8,'end.png',40);
    return graph.createNode({
      label: 'end',
      shape: 'rect',
      width: 120,
      height: 70,
      attrs: config.attrBaseConfig,
      markup: config.makeupBaseConfig,
      ports: endPorts,
    })
  }

  /**
   * 节点attr基础信息
   * @returns {*}
   */
  setNodeConfig = (title, borderColor, backgroundColor, shape, rx, ry,iconName,imgRefX,imgRefY) => {
    let config = {
      attrBaseConfig: {
        fo: {
          refWidth: '100%',
          refHeight: '100%',
        },
        foBody: {
          xmlns: Dom.ns.xhtml,
          style: {
            width: '100%',
            height: '100%',
            display: 'flex',
            justifyContent: 'center',
            alignItems: 'center',
            minWidth:'unset'
          },
        },
        'edit-text': {
          contenteditable: 'false',
          class: 'x6-edit-text',
          style: {
            width: '100%',
            textAlign: 'center',
            fontSize: 12,
            color: '#6a6c8a',
          },
        },
        body: {
          stroke: borderColor,
          strokeWidth: 1,
          fill: backgroundColor,
          rx: rx,
          ry: ry,
        },
        text: {
          fontSize: 14,
          fill: '#6a6c8a',
          textWrap: {
            text: title,
            width: -10,
          },
          refY: 55,
        },
        imageIcon:{
          'xlink:href': staticPath + "/ggeditor/formNode/"+iconName,
          refX: imgRefX ? imgRefX : 40,
          refY: imgRefY ? imgRefY : 5,
          width:39
        }
      },
      makeupBaseConfig: [
        {
          tagName: shape,
          selector: 'body',
        },
        {
          tagName: 'text',
          selector: 'text',
        },
        {
          tagName: 'foreignObject',
          selector: 'fo',
          children: [
            {
              ns: Dom.ns.xhtml,
              tagName: 'body',
              selector: 'foBody',
              children: [
                {
                  tagName: 'div',
                  selector: 'edit-text',
                },
              ],
            },
          ],
        },
        {
          tagName: 'g',
          children: [
            {
              tagName: 'image',
              selector: 'image',
            },
          ],
        },
        {
          tagName: 'image',
          selector: 'imageIcon',
        },
      ]
    };

    if (shape === 'circle') {
      config.attrBaseConfig.body = {
        stroke: borderColor,
        strokeWidth: 1,
        fill: backgroundColor,
      }
    } else if (shape === 'polygon') {
      config.attrBaseConfig.body = {
        stroke: borderColor,
        strokeWidth: 1,
        fill: backgroundColor,
        points: "0,35 60,0 120,35 60,70 0,35"
      }
    };

    return config;
  };

  render() {
    const { doPush,doSaveTemplate,pathInfo,name,formId,refreshName,openMoveClass,categoryId,pushTime } = this.props
    const platformInfo = window.localStorage.getItem("platformInfo") ? JSON.parse(window.localStorage.getItem("platformInfo")) : {}

    return (
      <div className={styles.wrap} id={'flowContent'}>
        <div className={styles.header} style={{ borderBottom: '1px solid #E8E8E8',borderTop: '1px solid #E8E8E8',marginTop:15,paddingRight:0 }}>
          <div className={styles.toolbar} style={{ width: '100%' }}>
            <ToolBar 
              resizeFn={this.resizeFn} 
              getDialogData={this.props.getDialogData} 
              doPush={doPush}
              doSaveTemplate={doSaveTemplate}
              pathInfo={pathInfo}
              name={name}
              formId={formId}
              refreshName={refreshName}
              openMoveClass={openMoveClass}
              categoryId={categoryId}
              pushTime={pushTime}
            />
          </div>
        </div>
        <div className={styles.content} style={{ paddingRight:24, background: '#ffffff',height:'calc(100vh - 205px)' }}>
          <div className={styles.sider} style={{ width: 170, padding: '10px 0 0 24px', height: '100%', background: '#FAFAFA' }}>
            <LeftDivs startDrag={this.startDrag} />
          </div>
          <div className={styles.panel} style={{height:'100%'}}>
            <div id="container" className="x6-graph" />
          </div>
        </div>
      </div>
    );
  }
}

export default connect(({ user }) => ({
  currentUser: user.currentUser,
}))(FormFlow);
